package com.gaofei.goods.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNodeConfig;
import cn.hutool.core.lang.tree.TreeUtil;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.gaofei.goods.api.StorageFeignApi;
import com.gaofei.goods.api.UserFeignApi;

import com.gaofei.goods.domain.Category;
import com.gaofei.goods.domain.TbCart;
import com.gaofei.goods.domain.TbGoods;
import com.gaofei.goods.domain.TbOrder;
import com.gaofei.goods.service.CategoryService;
import com.gaofei.goods.service.TbCartService;
import com.gaofei.goods.service.TbGoodsService;
import com.gaofei.goods.service.TbOrderService;
import io.seata.spring.annotation.GlobalTransactional;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.assertj.core.error.ShouldBeToday;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

@Slf4j
@RestController
@RequestMapping("goods")
@Api(tags = "商品服务接口")
@CrossOrigin //临时解决下跨域问题,一旦使用网关,把这个注解注释了就可以
public class GoodsController {

    @Autowired
    private UserFeignApi userFeignApi;

    @Autowired
    private CategoryService categoryService;

    @Autowired
    private TbGoodsService goodsService;

    @Autowired
    private TbCartService cartService;

    @Autowired
    private TbOrderService orderService;

    @Autowired
    private StorageFeignApi storageFeignApi;


    @Autowired
    private RedisTemplate redisTemplate;

    @RequestMapping("searchOrderWithNopay")
    public List<TbOrder> searchOrderWithNopay(@RequestParam("orderStatus") String orderStatus){
        QueryWrapper qw = new QueryWrapper();
        qw.eq("order_status", orderStatus);
        List list = orderService.list(qw);
        return list;
    }

    @RequestMapping("updateOrderStatus")
    public String updateOrderStatus(@RequestParam("orderId") Integer orderId){
        QueryWrapper<TbOrder> tbOrderQueryWrapper = new QueryWrapper<>();
        tbOrderQueryWrapper.eq("id", orderId);
        TbOrder one = orderService.getOne(tbOrderQueryWrapper);
        one.setOrderStatus("已支付");
        one.setUpdateTime(new Date());
        orderService.updateById(one);
        return "success";
    }

    /**
     * 创建订单
     * @param carts
     * @return
     */
    @RequestMapping("makeOrderAndPay")
    @SentinelResource(value = "makeOrderAndPay",blockHandler = "handleException")
    @Transactional //控制事务,下单之后扣库存,由于减库存操作是调用的另外一个微服务,因此无法回滚--->分布式事务问题
    @GlobalTransactional(rollbackFor = Exception.class) //分布式事务的注解
    public Object makeOrderAndPay(@RequestBody List<TbCart> carts){
        //1.下单
        TbOrder tbOrder = new TbOrder();
        StringBuffer goodsId = new StringBuffer();
        BigDecimal amount = new BigDecimal("0");
        for (TbCart cart : carts) {
            goodsId.append(cart.getGoodsId()+",");
            amount=amount.add(cart.getTotalPrice());
        }
        tbOrder.setOrderStatus("待支付");
        tbOrder.setGoodsId(goodsId.toString());
        tbOrder.setTotalAmount(amount);
        tbOrder.setCreateTime(new Date());
        tbOrder.setUserId(1);
        System.out.println("保存前:"+tbOrder);
        orderService.save(tbOrder);  //1.下单============ 加上     取消数据源的本地代理配置
        //2.删除购物车数据
        //3.减库存
        storageFeignApi.reduce();//2.减库存=========

//        int i = 1/0;
        System.out.println("保存后:"+tbOrder);

        HashMap<String, Object> result = new HashMap<>();
        result.put("msg", "success");
        result.put("orderId", tbOrder.getId());
        result.put("amount", tbOrder.getTotalAmount());
        return result;
    }

    @RequestMapping("cartList")
    public Object cartList(){
        //自己查询的一对多的方法
        List<TbCart> list = cartService.findCartList();
        return list;
    }

    @RequestMapping("addCart")
    public String addCart(Integer goodsId){
        if(goodsId==0||goodsId==null){
            return "error";
        }
        TbGoods goods = goodsService.getById(goodsId);

        //合并购物项
        //1.根据用户id和商品id 查询是否有对应的购物车数据
        QueryWrapper<TbCart> qw = new QueryWrapper<>();
        qw.eq("goods_id", goodsId);
        qw.eq("user_id", "1");
        TbCart one = cartService.getOne(qw);
        //2.如果有对应数据,更新购物车(合并购物项)
        if(one!=null){
            one.setBuyNum(one.getBuyNum()+1);
            one.setTotalPrice(goods.getGoodsPrice().multiply(new BigDecimal(one.getBuyNum())));
            cartService.updateById(one);
            return "success";
        }
        //3.没有-->添加购物车
        //根据商品id查询商品
        TbCart tbCart = new TbCart();
        tbCart.setGoodsId(goodsId);
        tbCart.setBuyNum(1);
        tbCart.setTotalPrice(goods.getGoodsPrice().multiply(new BigDecimal("1")));
        tbCart.setUserId(1);
        cartService.save(tbCart);
        return "success";
    }

    /**
     * 添加商品
     * @param goods
     * @return
     */
    @RequestMapping("save")
    @Transactional //开启事务控制
    public String save(@RequestBody Map goods){
        log.info("商品信息:{}",goods);//商品信息:xxxx
        TbGoods tbGoods = new TbGoods();
        BeanUtil.copyProperties(goods,tbGoods);
        List<String> categoryId = (List) goods.get("categoryId");
        StringBuilder sb = new StringBuilder();
        for (String id : categoryId) {
            sb.append(id + ",");
        }
        tbGoods.setCategoryId(sb.toString());
        log.info("====:{}",sb);
        log.info("封装后的商品信息:{}",tbGoods);
        goodsService.save(tbGoods); //往数据库中添加商品
        return "success";
    }


    /**
     * 上传商品图片
     * @return
     */
    @RequestMapping("uploadImg")
    public String uploadImg(@RequestParam("file") MultipartFile file) throws IOException {
        //1.获取上传过来的文件格式后缀
        String originalFilename = file.getOriginalFilename();//1.jpg
        String hz = originalFilename.substring(originalFilename.lastIndexOf("."), originalFilename.length());//.jpg
        String newFileName = UUID.randomUUID().toString()+hz;
        file.transferTo(new File("D:/upload/"+newFileName));
        return "http://localhost:8083/goods/upload/"+newFileName;
    }

    /**
     * 商品列表页面
     * @return
     */
    @RequestMapping("goodsList")
    public Object goodsList(Integer pageNum,Integer pageSize,String searchKey){
        if(searchKey==null){
            return goodsService.page(new Page<>(pageNum, pageSize));
        }
        QueryWrapper<TbGoods> qw = new QueryWrapper<>();
        qw.like("goods_name", searchKey);
        Page<TbGoods> page = goodsService.page(new Page<>(pageNum, pageSize),qw);
        return page;
    }


    @RequestMapping("addCategory")
    public String addCategory(@RequestBody Category category){
        categoryService.save(category);
        //为了保证,redis和mysql数据同步,(增删改的时候)删除redis中的数据
        redisTemplate.delete("catesList");
        return "success";
    }

    /**
     * 分类层级数据的展示
     * @return
     */
    @RequestMapping("categorys")
    public List<Tree<String>> getCates(){
//        1.先看redis中有没有分类数据::::catesList:[]
        List<Category> redisCatesList = redisTemplate.opsForList().range("catesList", 0, -1);
//        2.如果有--->直接返回redis中的数据
        if(redisCatesList!=null && redisCatesList.size()>0){
//        if(redisTemplate.hasKey("catesList")){  xxxxxxxxx错误的
            System.out.println("返回了redis中的数据!!!!!!!!!!!!!!!");
            return makeTrees(redisCatesList);
        }
            //        3.如果没有-->从数据库查询一份,并且保存到redis中,并返回
            //从数据库查询分类信息
            List<Category> list = categoryService.list();
            System.out.println("返回了数据库中的数据!!!!!!!!!!!!!!!");
            redisTemplate.opsForList().rightPushAll("catesList",list);
            List<Tree<String>> trees = makeTrees(list);
            return trees;

    }

    public List<Tree<String>> makeTrees(List<Category> list){
        //配置
        TreeNodeConfig treeNodeConfig = new TreeNodeConfig();
        // 自定义属性名 都要默认值的 ,返回前端的json的key值
        treeNodeConfig.setWeightKey("orders");
        treeNodeConfig.setIdKey("id");
        treeNodeConfig.setParentIdKey("pid");
        treeNodeConfig.setNameKey("name");
        // 最大递归深度
        treeNodeConfig.setDeep(3);
        //转换器
        List<Tree<String>> treeNodes = TreeUtil.build(list, "0", treeNodeConfig,
                (treeNode, tree) -> {
                    tree.setId(treeNode.getId()+"");
                    tree.setParentId(treeNode.getPid()+"");
                    tree.setWeight(treeNode.getOrders());
                    tree.setName(treeNode.getName());
                    // 扩展属性 ...
//                    tree.putExtra("extraField", 666);
//                    tree.putExtra("other", new Object());
                });

        return treeNodes;
    }

    @RequestMapping(value = "test1",method = RequestMethod.GET)
//    @GetMapping("test1")
    @SentinelResource(value = "test1"/*,blockHandler = "handleException"*/)
    @ApiOperation(value = "测试限流的接口", notes = "测试限流的接口")
    public String test1(){
        return "test111111111111";
    }

    public String handleException(BlockException exception){
        return "流量过大,稍后再试!!!";
    }

    @GetMapping ("aa")
    @ApiOperation(value = "测试远程调用的接口", notes = "测试远程调用的接口")
    public Object aa(){
        return userFeignApi.list();
    }
}
